package com.krtech.wecard.module.oauth2;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Handle;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.krtech.wecard.framework.aop.Metrics;
import com.krtech.wecard.framework.security.Inner;
import com.krtech.wecard.module.oauth2.vo.ClientSecretVo;
import com.krtech.wecard.module.pub.entity.ApplicationManagement;
import com.krtech.wecard.module.pub.service.ApplicationManagementService;
import com.krtech.wecard.module.sys.entity.SysKeyValue;
import com.krtech.wecard.module.sys.enums.SysEnums;
import com.krtech.wecard.module.sys.service.SysKeyValueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Sa-OAuth2 Server端 控制器
 */
//@Metrics
@RestController
public class SaOAuth2ServerController {

    @Autowired
    private SysKeyValueService keyValueService;

    @Autowired
    private ApplicationManagementService applicationManagementService;

    public List<ClientSecretVo> getClientAndSecretList(){
        List<ApplicationManagement> list = applicationManagementService.list();

        List<ClientSecretVo> applicationClientSecretList = new ArrayList<>();

        if (list.size() > 0){
            applicationClientSecretList = list.stream().map(applicationManagement -> {
                ClientSecretVo clientSecretVo = new ClientSecretVo();
                clientSecretVo.setClientId(applicationManagement.getAppKey());
                clientSecretVo.setSecretId(applicationManagement.getAppSecret());
                return clientSecretVo;
            }).collect(Collectors.toList());
        }


        SysKeyValue globalKeyAndSecret = keyValueService.getOne(new QueryWrapper<SysKeyValue>()
                .eq(SysKeyValue.COL_SYS_NAME, SysEnums.GLOBAL_KEY_AND_SECRET));

        if (globalKeyAndSecret != null){
            ClientSecretVo clientSecretVo = new ClientSecretVo();
            clientSecretVo.setClientId(globalKeyAndSecret.getSysKey());
            clientSecretVo.setSecretId(globalKeyAndSecret.getSysValue());
            applicationClientSecretList.add(clientSecretVo);
        }

        return applicationClientSecretList;
    }

    // 处理所有OAuth相关请求
    @Inner(value = false)
    @RequestMapping("/oauth2/*")
    public Object request( HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");

        SysKeyValue oauth2direct = keyValueService.getOne(new QueryWrapper<SysKeyValue>()
                .eq(SysKeyValue.COL_SYS_NAME, WecardOAuth2Enums.MIP_OAUTH2RE_DIRECT));

        SysKeyValue domain = keyValueService.getOne(new QueryWrapper<SysKeyValue>()
                .eq(SysKeyValue.COL_SYS_NAME, WecardOAuth2Enums.DOMAIN));


        System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl());

        List<ClientSecretVo> clientAndSecretList = getClientAndSecretList();
        Object o = WecardOAUTH2Handle.serverRequest(domain.getSysValue(),oauth2direct.getSysValue(),clientAndSecretList);
        return o;
    }

    // Sa-OAuth2 定制化配置
    @Autowired
    public void setSaOAuth2Config(SaOAuth2Config cfg) {
        cfg.
                //未登陆时候重定向到前端小程序
                // 配置：未登录时返回的View
                        setNotLoginView(() -> {
//                    String msg = "当前会话在SSO-Server端尚未登录，请先访问"
//                            + "<a href='/oauth2/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"
//                            + "进行登录之后，刷新页面开始授权";
                    String msg = "<script >window.location.href = \"http://10.10.103.241:8080/#/pointLogin\"</script>";
                    return msg;
                }).
                //
                // 配置：登录处理函数
                        setDoLoginHandle((name, pwd) -> {
                    if("sa".equals(name) && "123456".equals(pwd)) {
                        StpUtil.login(10001);
                        return SaResult.ok();
                    }
                    return SaResult.error("账号名或密码错误");
                }).
                // 配置：确认授权时返回的View
                        setConfirmView((clientId, scope) -> {
                    String msg = "<p>应用 " + clientId + " 请求授权：" + scope + "</p>"
                            + "<p>请确认：<a href='/oauth2/doConfirm?client_id=" + clientId + "&scope=" + scope + "' target='_blank'> 确认授权 </a></p>"
                            + "<p>确认之后刷新页面</p>";
                    return msg;
                })
        ;
    }

    // 全局异常拦截
    @ExceptionHandler
    public SaResult handlerException(Exception e) {
        e.printStackTrace();
        return SaResult.error(e.getMessage());
    }

}
